/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.customactions.flexunit.runner
{
	import net.customactions.flexunit.listener.SuitableListener;

	import org.flexunit.runner.FlexUnitCore;
	import org.flexunit.runner.notification.IRunListener;

	import flash.display.Sprite;
	import flash.events.Event;

	/**
	 * Default implementation of a FlexUnit Runner.
	 * 
	 * <p>Extends this class to configure your own testing properties.</p>
	 * 
	 * @includeExample FlexUnitRunnerExample.as -noswf
	 * 
	 * @author Romain Ecarnot
	 * 
	 * @langversion 3.0
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @productversion FDT 3.5
	 */
	public class FlexUnitRunner extends Sprite
	{
		//--------------------------------------------------------------------
		// Private properties
		//--------------------------------------------------------------------
		
		/**
		 * @private
		 * The FlexUnitCore instance.
		 */
		private var _unitCore : FlexUnitCore;

		/**
		 * @private 
		 * Tests list to run.
		 */
		private var _testList : Array;

		/**
		 * @private
		 * Stores SuitableListener references
		 */
		private var _listeners : Vector.<SuitableListener>; 

		
		//--------------------------------------------------------------------
		// Public API
		//--------------------------------------------------------------------
		
		/**
		 * Creates instance.
		 */
		public function FlexUnitRunner()
		{
			addEventListener(Event.ADDED_TO_STAGE, _runTests);
		}

		/**
		 * Adds passed-in listener to FlexUnitCore listeners collection.
		 * 
		 * @param listener	FlexUnitCore listener.
		 */
		final protected function addListener(listener : IRunListener) : void
		{
			_unitCore.addListener(listener);
			
			if(listener is SuitableListener && _listeners.indexOf(listener) < 0)
			{
				_listeners[_listeners.length] = listener as SuitableListener;
			}
		}

		/**
		 * Overrides this method to configure your testing session.
		 */
		protected function configure() : void
		{
		}

		/**
		 * Adds passed-in arguments as TestSuites or TestCase to run.
		 * 
		 * @param args	List of TestSuite or TestCase to run
		 */
		final protected function addTest(...args) : void
		{
			for each (var test : * in args) _testList.push(test); 
		}
		
		
		//--------------------------------------------------------------------
		// Private methods
		//--------------------------------------------------------------------
		
		/**
		 * @private
		 * Runner is added to stage, initializes basic properties and 
		 * starts template method to run the test. 
		 */
		private function _runTests(event : Event = null) : void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, _runTests);
			
			_testList = [];
			_listeners = new Vector.<SuitableListener>();
			_unitCore = new FlexUnitCore();
			
			configure();
			
			_run();
		}

		/**
		 * @private
		 * Starts FlexUnit testing using runner properties.
		 */
		private function _run() : void
		{
			if(_listeners.length > 0)
			{
				for each (var listener : SuitableListener in _listeners) 
				{
					listener.registerSuite(_testList);
				}
			}
			
			_unitCore.run.apply(_unitCore, _testList);
			
			_testList = [];
		}
	}
}